// 在 TS 的类型系统中，除去直观的一些 number, string, boolean 等类型外，我们也会见到诸如 any、void 和 never 这样

// any 类型
// 在一些情况下，如果我们无法确定变量的类型时（或者无需确认类型时），我们可以将其指定为 any 类型。
function isNumber(value: any) {
    return typeof value === 'number';
}

// any 类型的特点
//    1.允许赋值为任意类型
let value: any = 'seven';
value = 7;

//    2.可以访问任意属性和方法
let value2: any = 'hello';

// 可以访问任意属性
console.log(value2.name); // undefined
console.log(value2.name.firstName); // 报错

// 可以调用任意方法
value2.setName('Jerry');
value2.setName('Jerry').sayHello();

// void 类型
// 1.没有返回值的函数，其返回值类型为 void
function warnUser(): void {
    console.log("This is my warning message");
}

// 申明为 void 类型的变量，只能赋予 undefined 

let unusable: void = undefined;
let voidNull:void = undefined



// never
// never 类型表示永远不会有值的一种类型。(很抽象是不是)

// 1.never类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型
// 返回never的函数必须存在无法达到的终点

// 因为总是抛出异常，所以 error 将不会有返回值
function error(message: string): never {
    throw new Error(message);
}

// 因为存在死循环，所以 infiniteLoop 将不会有返回值
function infiniteLoop(): never {
    while (true) {
    }
}

// 永远不可能存在的情况：
const foo = 123;
if (foo !== 123) {
    const bar = foo;    // bar: never
}

// never 类型的一个应用场景
enum Letter {
    A,
    B,
    C,
}

let letter:number = 1
// 假如我们有如下一个通用型的业务逻辑
// ../../business.ts
switch (letter) {
    case Letter.A:
        // ...
        break;
    case Letter.B:
        // ...
        break;
    case Letter.C:
        // ...
        break;
    default:
        /**
         * 这里的我们通常会有两种做法：
         *      1. 给一个默认的状态
         *      2. 将其等同于A/B/C的一种
         *
         * 但其实我们默认代码不应该存在进入这一分支的可能，一旦进入意味着程序存在了某种异常的状态。
         **/
        const check: never = letter; // 加这个，当进入到default分支，就会报错，避免未来在引入新的枚举值时候引发隐藏Bug,
        break;
}

